/**
 * 游戏控制器
 */
class gameController extends Frame.MVC.Controller {
  view: gameView;
  model: gameModel;

  nextFruit: fruit;

  gameOverCount = 0;

  gameBegin: boolean = false;

  deadLineTwinkle = false;
  deadLineTwinkling = false;
  shootable = false;

  constructor() {
    super();
  }
  //视图首次创建
  viewInit() {
    //每帧执行
    this.view.addEventListener(egret.Event.ENTER_FRAME, this.enterFrame, this);

    //消息监听
    Frame.Message.addListener("restart", () => {
      this.restart();
    }, this);

    this.view.touchGrp.addEventListener(egret.TouchEvent.TOUCH_END, this.clickDropFruit, this);

    this.view.fruitMoveGrp.setChildrenSortMode(egret.ChildrenSortMode.INCREASE_Y);

    //创建物理世界
    this.model.phyWorld = physicsUtil.getInstance().createPhyWorld(-15);
    //创建材质碰撞规则
    this.createMaterial();

    let stageH = Frame.Display.stage.stageHeight;
    let stageW = Frame.Display.stage.stageWidth;

    //创建四周围栏
    this.createPanel(0, stageH - 10, 0);
    this.createPanel(0, 0, -Math.PI / 2);
    this.createPanel(stageW, 0, Math.PI / 2);

    //发送碰撞信息
    physicsUtil.getInstance().phyWorld.on("beginContact", this.contact, this);

  }


  viewOpen() {
    this.restart();
  }
  //重新开始
  restart() {
    this.shootable = true;
    this.deadLineTwinkle = false;
    this.view.deadLine.visible = false;


    this.gameBegin = true;
    let fruitList = this.model.fruitList;
    for (let i in fruitList) {
      let fruit = <fruit>fruitList[i];
      fruit.phyBody.world && fruit.phyBody.world.removeBody(fruit.phyBody);
      fruit.removeFromParent();
    }
    this.view.scoreLbl.text = "0";
    this.model.score = 0;
    this.deadLineTwinkling = false;


    //创建水果
    this.createFruit();
  }
  enterFrame(evt) {
    //判断是否超线三秒
    for (let i in this.view.fruitMoveGrp.$children) {
      if ((this.view.fruitMoveGrp.$children[i].y - this.view.fruitMoveGrp.$children[i].height / 2) < this.view.deadLine.y) {
        this.gameOverCount += 1;
        if (this.gameOverCount >= 60) {
          //亮红线
          this.view.deadLine.visible = true;
          //红线闪烁
          this.deadLineTwinkle = true;
        }

      }
      else {
        if (Number(i) == this.view.fruitMoveGrp.$children.length - 1) {
          this.gameOverCount = 0;
          this.deadLineTwinkle = false;
          this.view.deadLine.visible = false;

        }
      }
    }
    if (this.gameOverCount >= 300) {
      this.gameOver();
    }
    this.deadLineTwinkleFunc();
  }
  //红线闪烁
  private deadLineTwinkleFunc() {
    if ((!this.deadLineTwinkle) || (this.deadLineTwinkling)) {
      return;
    }
    this.deadLineTwinkle = false;
    this.deadLineTwinkling = true;
    egret.Tween.get(this.view.deadLine).to({
      alpha: 1
    }, 300).to({
      alpha: 0.3
    }, 300).call(() => {
      this.deadLineTwinkling = false;
    });

  }
  private gameOver() {
    this.gameOverCount = 0;
    this.shootable = false;


    let fruitList = this.model.fruitList;

    let highestFruit = fruitList[0];

    for (let i in fruitList) {
      let fruit = <fruit>fruitList[i];
      if (fruit.y < highestFruit.y) {
        highestFruit = fruit;
      }
    }
    egret.Tween.get(highestFruit).to({
      alpha: 0.3
    }, 100).to({
      alpha: 1
    }, 100).to({
      alpha: 0.3
    }, 100).to({
      alpha: 1
    }, 100).to({
      alpha: 0.3
    }, 100).to({
      alpha: 1
    }, 100).call(() => {
      //开启结束view
      this.gameBegin && Frame.Message.dispatch("gameOver");
      this.gameBegin = false;
    })



  }
  //创建水果
  private createFruit() {
    if (this.view.fruitGenerateGrp.numChildren != 0) {
      return;
    }

    let rStatus = Math.floor(Math.random() * (this.model.fruitRadius.length / 3));
    let f = new fruit({ position: [0, 0], radius: this.model.fruitRadius[rStatus.toString()], status: rStatus, mass: rStatus + 1 });
    f.visible = false;
    this.view.fruitGenerateGrp.addChild(f);
    f.visible = true;
    f.x = f.width / 2;
    f.y = f.height / 2;
    this.nextFruit = f;
  }
  //点击操作
  private clickDropFruit(evt) {
    if ((!this.nextFruit) || (!this.shootable)) {
      return;
    }
    let nextF = this.nextFruit;
    let rX = evt.stageX + (Math.random() > 0.5 ? -1 : 1) * (Math.random() * 10);
    if (rX < (nextF.width / 2) + 1) {
      rX = (nextF.width / 2) + 1;
    }
    else if (rX > (this.view.width - 1 - nextF.width / 2)) {
      rX = (this.view.width - 1 - (nextF.width / 2));
    }

    this.nextFruit = null;
    nextF.changeParentGrp(this.view.fruitMoveGrp);
    nextF.setPos(rX, nextF.y);
    this.model.fruitList.push(nextF);
    egret.Tween.get(nextF).to({
      x: rX, y: nextF.y
    }, Math.abs(nextF.x - rX) / this.model.fruitMoveSpeed).call(() => {
      nextF.setPhysicsBody(nextF.data.radius);
      nextF.phyShape.material = this.model.material["fruit"];

      setTimeout(() => {
        this.createFruit();
      }, 800);
    }, this);

  }
  //碰撞后的处理
  private contact(msg) {
    if ((msg.bodyA.displays[0].type != "fruit") || (msg.bodyB.displays[0].type != "fruit")) {
      return;
    }
    if (msg.bodyA.displays[0].data.status == msg.bodyB.displays[0].data.status) {
      let objA = msg.bodyA.displays[0].y > msg.bodyB.displays[0].y ? msg.bodyA.displays[0] : msg.bodyB.displays[0];
      let objB = msg.bodyA.displays[0].y > msg.bodyB.displays[0].y ? msg.bodyB.displays[0] : msg.bodyA.displays[0];
      if ((objA.combined) || (objB.combined)) {
        return;
      }

      objA.combined = true;
      objB.combined = true;
      this.fruitDisappear(objB, objA);
      return;
    }
  }
  //水果消失
  private fruitDisappear(objA: fruit, objB: fruit) {
    if (objA.data.status >= (this.model.fruitRadius.length - 1)) {
      return;
    }
    objA.phyBody.world && objA.phyBody.world.removeBody(objA.phyBody);
    objB.phyBody.world && objB.phyBody.world.removeBody(objB.phyBody);

    if (this.model.fruitList.indexOf(objA) != -1) {
      this.model.fruitList.splice(this.model.fruitList.indexOf(objA), 1);
    }
    if (this.model.fruitList.indexOf(objB) != -1) {
      this.model.fruitList.splice(this.model.fruitList.indexOf(objB), 1);
    }

    objB.data.status = objB.data.status + 1;

    egret.Tween.get(objA).to({
      x: objB.x,
      y: objB.y
    }, 100).call(() => {
      objA.removeFromParent();
      this.fruitChangeStatus(objB, objB.data.status);
    }, this);
  }
  //水果状态改变
  private fruitChangeStatus(obj: fruit, status = 0) {
    let x = obj.x;
    let y = obj.y;
    obj.data.status = status;
    obj.statusLbl.text = status.toString();
    obj.phyBody.world && obj.phyBody.world.removeBody(obj.phyBody);
    obj.removeFromParent();
    obj = null;
    let newF = new fruit({ position: [x, y], radius: 1, status: status, mass: (status + 1) });
    this.view.fruitMoveGrp.addChild(newF);
    this.model.fruitList.push(newF);

    this.showJuice(status, x, y);

    newF.setPhysicsBody(this.model.fruitRadius[status]);
    newF.scaleDisplayToNormal(this.model.fruitRadius[status], 100);
    physicsUtil.getInstance().phyWorld.addBody(newF.phyBody);
    newF.phyBody.applyForce([0, 1], newF.phyBody.position);

    this.model.score += status * 2;
    this.view.scoreLbl.text = this.model.score.toString();

  }
  //显示果汁
  private showJuice(status, x, y) {

    let juiceImg = new eui.Image(`juice-${status - 1}_png`);
    juiceImg.alpha = 0.3;
    juiceImg.scaleX = 0.1;
    juiceImg.scaleY = 0.1;
    juiceImg.x = x;
    juiceImg.y = y;
    juiceImg.rotation = Math.random() * 180 * (Math.random() > 0.5 ? 1 : -1);
    this.view.effectGrp.addChild(juiceImg);

    juiceImg.anchorOffsetX = juiceImg.width / 2;
    juiceImg.anchorOffsetY = juiceImg.height / 2;


    egret.Tween.get(juiceImg).to({
      scaleX: 0.5,
      scaleY: 0.5,
      alpha: 0.6,
    }, 100).to({
      alpha: 0.4
    }, 300).to({
      alpha: 0.1
    }, 1000).call(() => {
      juiceImg.parent && juiceImg.parent.removeChild(juiceImg);
    });
  }
  //添加边界
  private createPanel(x, y, angle) {
    let shape = new egret.Shape();
    shape.graphics.beginFill(0xffffff);
    shape.graphics.drawRect(0, 0, Frame.Display.stage.stageWidth, 10);
    shape.graphics.endFill();

    let panel: p2.Plane = new p2.Plane();
    panel.material = this.model.material["wall"];
    let pos = physicsUtil.getInstance().posEgretToP2(x, y);
    let planeBody = new p2.Body({ position: [pos[0], pos[1]], mass: 0 });
    planeBody.angle = angle;
    planeBody.addShape(panel);
    planeBody.displays = [shape];
    this.view.addChild(shape);
    physicsUtil.getInstance().phyWorld.addBody(planeBody);

  }
  //创建墙
  createWall({ width = 100, height = 10, color = 0xffffff, mass = 0, position = [0, 0] }): p2.Body {
    let [x, y] = physicsUtil.getInstance().posEgretToP2(position[0], position[1]);
    let shape = new egret.Shape();
    shape.graphics.beginFill(color);
    shape.graphics.drawRect(0, 0, width, height);
    shape.graphics.endFill();

    let phyShape = new p2.Box({ width: width / physicsUtil.getInstance().phyFactor, height: height / physicsUtil.getInstance().phyFactor });
    phyShape.material = this.model.material["wall"]
    let phyBody: p2.Body =
      new p2.Body({
        mass: mass,
        position: [x, y]
      });
    phyBody.addShape(phyShape);
    physicsUtil.getInstance().phyWorld.addBody(phyBody);
    phyBody.displays = [shape];

    shape.width = (<p2.Box>phyShape).width * physicsUtil.getInstance().phyFactor;
    shape.height = (<p2.Box>phyShape).height * physicsUtil.getInstance().phyFactor;
    shape.anchorOffsetX = shape.width / 2;
    shape.anchorOffsetY = shape.height / 2;

    return phyBody;
  }
  //创建碰撞规则
  private createMaterial() {
    //水果与墙的碰撞规则
    let opt1 = {
      surfaceVelocity: 0,
      restitution: 0.1,
      friction: 0.3,
      stiffness: 1e50000,
      relaxation: 46,
      frictionRelaxation: 1e5,
      frictionStiffness: 1e5000
    }
    var material1 = new p2.ContactMaterial(this.model.material["fruit"], this.model.material["wall"], opt1);
    this.model.phyWorld.addContactMaterial(material1);
    var material2 = new p2.ContactMaterial(this.model.material["wall"], this.model.material["fruit"], opt1);
    this.model.phyWorld.addContactMaterial(material2);
    //水果与水果的碰撞规则
    let opt2 = {
      surfaceVelocity: 0,
      restitution: 0.1,
      friction: 0.3,
      stiffness: 1e50000,
      relaxation: 46,
      frictionRelaxation: 1e5,
      frictionStiffness: 1e5000
    }
    var material3 = new p2.ContactMaterial(this.model.material["fruit"], this.model.material["fruit"], opt2);
    this.model.phyWorld.addContactMaterial(material3);
  }

}